<?php

/* 
 * 核心方法
 */

/**
 * 全能采集器 by torn
 * @param url: str 'http://..'
 * @param rtype: int [0]无处理 [1]html转码 [2]反序列化 [3]debug断言
 * @param datas: arr
 * 	['post']arr 'k' => 'v' 
 * 	['cookie']str ' k=v; k1=v2;'
 * 	['referer']str 'http://..'
 * 	['timeout']int 30
 * 	['ua']str 'mozilla..'
 * @return arr:
 * 	[0]str html_context, 
 * 	[1]cookie: arr [0]str ' k=v; k1=v2;' [any]arr 'k' => 'v'
 *	[2]$http_response_header arr
 */
function gather_bak($url, $datas = null, $rtype = 0) {
	### 初始化参数
	//filter_var($url, FILTER_VALIDATE_URL) || die('Error url: ' . $url);
	$method = $datas['post'] ? 'POST' : 'GET';
	$post = isset($datas['post']) && count($datas['post']) ? http_build_query($datas['post']) : '';
	$cookie = isset($datas['cookie']) ? $datas['cookie'] : '';
	$ua = isset($datas['ua']) ? $datas['ua'] : '';
	$referer = isset($datas['referer']) ? $datas['referer'] : '';
	$timeout = isset($datas['timeout']) && $datas['timeout'] > 0 ? $datas['timeout'] : '60';
	$ajax = isset($datas['ajax']) ? "X-Requested-With: XMLHttpRequest\r\n" : '';
	$opts = array(
		'http' => array(
			'method' => $method,
			'header' => 
			//"Content-type: application/x-www-form-urlencoded\r\n" .
			//"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n" .
			//"Accept-Encoding: gzip, deflate, sdch\r\n" .
			//"Accept-Language: zh-CN\r\n" .
			"Cache-Control: max-age=0\r\n" .
			"Connection: keep-alive\r\n" .
			$ajax .
			"Content-length: " . strlen($post) . "\r\n" .
			"User-Agent: " . $ua . "\r\n" .
			"Pragma: no-cache\r\n" .
			"Referer: " . $referer . "\r\n" .
			"Cookie: " . $cookie . "\r\n",
			'content' => $post,
			'timeout' => $timeout
		)
	);
	if (!$post) {
		unset($opts['http']['content']);
	}
	$cxContext = stream_context_create($opts);
	### 扒取html/cookie
	$sFile = file_get_contents($url, false, $cxContext);
	$cookieFoo = array();
	if (preg_match_all("/Set-Cookie:\s+(([^=]+)=(\S+);)/i", implode("/r/n", $http_response_header), $cookies, PREG_SET_ORDER)) {
		$cookieFoo[0] = '';
		foreach ($cookies AS $v) {
			$cookieFoo[$v[2]] = $v[3];
			$cookieFoo[0] .= $v[1] . ' ';
		}
	}
	### 返回/输出
	if (!$rtype) {
		return array($sFile, $cookieFoo, $http_response_header);
	} else if ($rtype == 1) {
		return array(htmlspecialchars($sFile), $cookieFoo, $http_response_header);
	} else if ($rtype == 2) {
		return array(unserialize($sFile), $cookieFoo, $http_response_header);
	} else {
		echo '<pre>' . var_export($http_response_header, TRUE) . '</pre>'; // 头信息
		die(htmlspecialchars($sFile));
		die($sFile);
	}
}

function gather($url, $datas = null, $rtype = 0) {
	if (!function_exists('stream_socket_client')) {
		return gather_bak($url, $datas, $rtype); // 若不支持socket函数则换用 file_get_contents
	}
	if (!class_exists('Snoopy')) loadClass('snoopy');
	$post = isset($datas['post']) && count($datas['post']) ? $datas['post'] : FALSE;
	$cookie = isset($datas['cookie']) ? $datas['cookie'] : $GLOBALS['COOKIE'];
	$ua = isset($datas['ua']) ? $datas['ua'] : 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/4.4.3.4000 Chrome/30.0.1599.101 Safari/537.36';
	$referer = isset($datas['referer']) ? $datas['referer'] : '';
	$timeout = isset($datas['timeout']) && $datas['timeout'] > 0 ? $datas['timeout'] : '30';
	$ajax = $datas['ajax'] ? "XMLHttpRequest" : '';
	###
	$snoopy = new Snoopy; // 需预先引入Snoopy类
	$snoopy->agent = $ua; //伪装浏览器
	$snoopy->read_timeout = $timeout;
	$snoopy->referer = $referer; //伪装来源页地址 http_referer
	$snoopy->rawheaders["Cookie"] = $cookie;
	if ($ajax) $snoopy->rawheaders['X-Requested-With'] = $ajax;
	//$snoopy->cookies = $cookie;
	$snoopy->rawheaders["Pragma"] = "no-cache"; //cache 的http头信息
	//$snoopy->rawheaders["X_FORWARDED_FOR"] = "127.0.0.101"; //伪装ip
	$snoopy->expandlinks = true; // 补全连接
	$snoopy->maxredirs = 5; //重定向次数
	if ($post) {
		$files = []; // 需上传的文件数组
		if (is_array($post['files']) && $post['files']) {
			$files = $post['files'];
			unset($post['files']);
		}
		$snoopy->set_submit_multipart(); //$snoopy->_submit_type = "multipart/form-data"; // post提交
		$snoopy->submit($url, $post, $files);
	} else {
		$snoopy->fetch($url);
	}
	### 扒取html/cookie
	$sFile = $snoopy->results;
	### 验证
	/*if (preg_match('/YJS\s+\|([^\|]+)\|([\S\|]+)/Ui', $File, $verifArr)) { // YJS |34ab6743dd9de2a29f7fdd32568539ca|MTQyMTUzMTg5Mw== |challenge
		$_cookie = 'YJS=' . $verifArr[1] . ',' . $verifArr[2];
		$_datas = array(
			'referer' => $url,
			'ua' => $ua,
			'cookie' => $_cookie
		);
		return gather($url, $_datas);
	}*/
	$cookieFoo = array();
	if (preg_match_all("/Set-Cookie:\s+(([^=]+)=(\S+);)/i", implode("\r\n", $snoopy->headers), $cookies, PREG_SET_ORDER)) {
		$cookieFoo[0] = '';
		foreach ($cookies AS $v) {
			$cookieFoo[$v[2]] = $v[3];
			$cookieFoo[0] .= $v[1] . ' ';
		}
		$GLOBALS['COOKIE'] = $cookieFoo[0];
	}
	### 返回/输出
	if (!$rtype) {
		return array($sFile, $cookieFoo, $snoopy->headers);
	} else if ($rtype == 1) {
		return array(htmlspecialchars($sFile), $cookieFoo, $snoopy->headers);
	} else if ($rtype == 2) {
		return array(unserialize($sFile), $cookieFoo, $snoopy->headers);
	} else {
		//echo '<pre>' . var_export($snoopy->headers, TRUE) . '</pre>'; // 头信息
		var_dump($snoopy);
		die(htmlspecialchars($sFile));
	}
	
	/*if (curl_getinfo($ch, CURLINFO_HTTP_CODE) == '200') {
		$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
		$header = substr($response, 0, $headerSize);
		$body = substr($response, $headerSize);
	}*/
}

/**
* gzdecode：PHP 解压gzip
*/
if (!function_exists('gzdecode')) {
	function gzdecode ($data) {
		$flags = ord(substr($data, 3, 1));
		$headerlen = 10;
		$extralen = 0;
		$filenamelen = 0;
		if ($flags & 4) {
			$extralen = unpack('v' ,substr($data, 10, 2));
			$extralen = $extralen[1];
			$headerlen += 2 + $extralen;
		}
		if ($flags & 8) $headerlen = strpos($data, chr(0), $headerlen) + 1; // Filename
		if ($flags & 16) $headerlen = strpos($data, chr(0), $headerlen) + 1; // Comment
		if ($flags & 2) $headerlen += 2; // CRC at end of file
		$unpacked = @gzinflate(substr($data, $headerlen));
		if ($unpacked === FALSE) $unpacked = $data;
		return $unpacked;
	}
}

/**
* JSON encode 中文不乱码
*/

function JSON($arr, $convert = FALSE) {
	if (!is_array($arr)) return FALSE;
	if (version_compare(PHP_VERSION, '5.4.0') >= 0) return json_encode($arr, JSON_UNESCAPED_UNICODE); // 5.4+ 原生支持
	_arrayRecursive($arr, 'urlencode', true);
	$_json = json_encode($arr);
	$json = urldecode($_json);
	$convert && $json = mb_convert_encoding($json, 'UTF-8', 'CP936');
	return $json;
    
}

function _arrayRecursive(&$array, $function, $apply_to_keys_also = false) {
	static $_recursive_counter = 0;
	if (++$_recursive_counter > 1000) {
		die('possible deep recursion attack');
	}
	foreach ($array as $key => $value) {
		if (is_array($value)) {
			$_function = __FUNCTION__;
			$_function($array[$key], $function, $apply_to_keys_also);
		} else {
			$array[$key] = $function($value);
		}
 
		if ($apply_to_keys_also && is_string($key)) {
			$new_key = $function($key);
			if ($new_key != $key) {
				$array[$new_key] = $array[$key];
				unset($array[$key]);
			}
		}
	}
	$_recursive_counter--;
}

/**
* model 加载
*/

function loadModel($model = '', $module = '') {
	static $model_arr = array();
	$model = $model == '' ? CONTROLLER_NAME : $model;
	$module = $model == '' || $module == '' ? MODULE_NAME : $module;
	$modelPath = WEB_PATH . '/apps/' . $module . '/model/' . $model . '.mod.php';
	if (isset($model_arr[$modelPath])) return $model_arr[$modelPath];
	if (!file_exists($modelPath)) die('ERROR: No Model [' . $modelPath . ']');
	include $modelPath;
	$obj = new $module();
	$model_arr[$modelPath] =  $obj;
	return $obj;
}

/**
* config 加载
*/

function loadConfig($configFile) {
	$configFilePath = WEB_PATH . '/config/' . $configFile . '.cfg.php';
	file_exists($configFilePath) || die("error: configFile [$configFilePath] not found !");
	$config = include $configFilePath; // return $config
	array_merge(System::$config, $config); // 合并现有配置
}

/**
* 类库加载
*/

function loadClass($className, $dir = '') {
	$classPath = $dir == 'system' ? WEB_PATH . '/system/core/lib/' . $dir . '/' . $className . '.class.php' : WEB_PATH . '/extra/' . $dir . '/' . $className . '.class.php';
	file_exists($classPath) || die("error: classFile [$classPath] not found !");
	include $classPath;
}

/**
* 模板加载
*/

function template($file_name = '', $controller = '', $module = '') {
	if ($file_name == '' && $controller == '' && $module == '') {
		$module = MODULE_NAME;
		$controller = CONTROLLER_NAME;
		$file_name = ACTION_NAME;
		goto b;
	}
	$file_name = $file_name ? $file_name : ACTION_NAME;
	$module = $module != '' ? $module : MODULE_NAME;
	$controller = $controller != '' ? $controller : CONTROLLER_NAME;
	b:
	$file_name .= '.phtml';
	define('TEMP_PATH', './template/' . $module . '/' . $controller . '/');
	$path = TEMP_PATH . $file_name;
	return file_exists($path) ? $path : '';
}


/**
* debug 输出
*/

function dd($data, $type = 'exp') {
	//if (DEBUG != true) return false;
	if (!is_array($data)) {
		var_dump($data);
		return true;
	}
	$type_arr = array('dump', 'exp');
	if (!in_array($type, $type_arr)) $type = $type_arr[0];
	if ($type == 'dump') {
		var_dump($data);
	} else if ($type == 'exp') {
		echo '<pre>' . var_export($data, true) . '</pre>';
	}
}